package com.tool.grab.vpn.header;

/**
 * 传输层
 * UDP报文格式
 * ｜－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－｜U
 * ｜                      16 bit                       ｜                     16 bit                        ｜D
 * ｜                 源端口(local port)                ｜                目的端口(remote port)              ｜P
 * ｜－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－｜报
 * ｜                      16 bit                       ｜                     16 bit                        ｜头
 * ｜               总长度(total length)                ｜                 校验和(check sum)                 ｜长
 * ｜－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－｜8
 * ｜                                                  数据                                                  ｜y
 * ｜－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－｜e
 */

public class UDPPacket extends Packet{
    private static final String TAG = UDPPacket.class.getSimpleName();

    static final int SOURCE_PORT_BIT = 0;
    static final int DESTINATION_PORT_BIT = 2;
    static final int TOTAL_LENGTH_BIT = 4;
    static final int CHECK_SUM_BIT = 6;

    public UDPPacket(byte[] bytes , int... parameters){
        super(bytes,parameters);
    }

    /**
     * 获取UDP数据报源端口
     * @return
     */
    public int getLocalPort(){
        return bytes[SOURCE_PORT_BIT + offset]  << 8 | bytes[SOURCE_PORT_BIT + offset + 1] ;
    }

    /**
     * 获取UDP数据报目的端口
     * @return
     */
    public int getRemotePort(){
        return bytes[DESTINATION_PORT_BIT + offset] << 8 | bytes[DESTINATION_PORT_BIT + offset +1] ;
    }

    /**
     * 获取UDP数据报总长度
     * @return
     */
    public int getTotalLenth(){
        return bytes[TOTAL_LENGTH_BIT + offset] << 8 | bytes[TOTAL_LENGTH_BIT + offset + 1];
    }

    /**
     * 获取校验和
     * @return
     */
    public int getCheckSum(){
        return bytes[CHECK_SUM_BIT] << 8 | bytes[CHECK_SUM_BIT + 1];
    }

    /**
     * 检查校验和是否正确
     * @return
     */
    public boolean checkSum(){
        int sum = getSum();
        return (short)~sum == 0;
    }

    /**
     * 获取校验和
     * @return
     */
    private int getSum(){
        int sum = 0;

        for(int i = offset;i < validLength;i++){
            sum += bytes[i] << 8 | bytes[i + 1];
        }

        if((validLength - offset) % 2 > 0){
            sum += bytes[validLength - 1] << 8;
        }

        while ((sum>>16) > 0){
            sum = (sum >> 16) + (sum & 0xFFFF);
        }
        return sum;
    }

    /**
     * 刷新校验和
     */
    public void refreshCheckSum(){
        bytes[CHECK_SUM_BIT + offset] = 0;
        bytes[CHECK_SUM_BIT + offset + 1] = 0;
        int sum = getSum();

        bytes[CHECK_SUM_BIT + offset] = (byte) (~sum >> 8);
        bytes[CHECK_SUM_BIT + offset + 1] = (byte) (~sum);
    }


}
